package top.linyuxb.lycloud.rpc.starter.controller;

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import top.linyuxb.lycloud.rpc.starter.annotation.LyRpcVersion;
import top.linyuxb.lycloud.rpc.starter.common.FileUtils;
import top.linyuxb.lycloud.rpc.starter.properties.LyRpcServerProperties;

import java.io.File;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author linyuxb
 * @date 2024/1/13 4:20 下午
 * @desc rpc服务端控制器
 */
@Slf4j
@RestController
@RequestMapping(value = "/lyRpcServer")
public class LyRpcServerController {

    @Value("${ly-config.open:false}")
    private Boolean open = false;
    @Value("${ly-config.user:}")
    private String user = StringUtils.EMPTY;
    @Value("${ly-config.user-password:}")
    private String userPassword = StringUtils.EMPTY;

    @Resource
    private LyRpcServerProperties lyRpcServerProperties;
    @Resource
    private Map<String, Class<?>> serverClassMap;

    /**
     * rpc 服务调用
     *
     * @param req
     * @param user
     * @param password
     * @param version
     * @return
     */
    @PostMapping(value = "/getInfo")
    public Object lyRpc(@RequestBody JSONObject req,
                        @RequestHeader(value = "user", defaultValue = "") String user,
                        @RequestHeader(value = "password", defaultValue = "") String password,
                        @RequestHeader(value = "version", defaultValue = "") String version
    ) {
        if (open) {
            if (!Objects.equals(this.user, user) ||
                    !Objects.equals(this.userPassword, password)) {
                return "接口请求非法！";
            }
        } else {
            if (!Objects.equals(lyRpcServerProperties.getUser(), user) ||
                    !Objects.equals(lyRpcServerProperties.getPassword(), password)) {
                return "接口请求非法！";
            }
        }
        log.info("lyRpc:{}", JSON.toJSONString(req));
        String name = req.getString("name");
        String method = req.getString("method");
        String fileName = req.getString("fileName");
        JSONArray args = req.getJSONArray("args");
        Class<?> aClass = serverClassMap.get(name);
        List<?> collect = SpringUtil.getBeansOfType(aClass).values().stream().toList();
        // 默认第一个bean 处理逻辑
        Object bean = collect.get(0);
        for (Object o : collect) {
            LyRpcVersion annotation = o.getClass().getAnnotation(LyRpcVersion.class);
            if (StrUtil.isEmpty(version) && (Objects.isNull(annotation) || StrUtil.isEmpty(annotation.version()))) {
                bean = o;
                break;
            }
            if (StrUtil.isNotBlank(version) && Objects.nonNull(annotation) && Objects.equals(annotation.version(), version)) {
                bean = o;
                break;
            }
        }
        Method thisMethod = ReflectUtil.getMethodByName(aClass, method);
        Object[] array = args.toArray();
        if (StrUtil.isNotBlank(fileName)) {
            Parameter[] parameters = thisMethod.getParameters();
            for (int i = 0; i < parameters.length; i++) {
                if (parameters[i].getType().equals(File.class)) {
                    String fileInfo = (String) array[i];
                    array[i] = FileUtils.getBase64ToFile(fileInfo, fileName);
                }
            }
        }
        return ReflectUtil.invoke(bean, thisMethod, array);
    }

}
